4473. Максимум

 

Ваша задача очень простая и даже без большой легенды: просто нужно найти максимум на отрезке.

 

Вход. Сначала подаётся количество чисел n (1 ≤ n ≤ 105) в массиве. В следующей строке заданы n чисел – исходный массив a1, a2, ..., an (-109ai ≤ 109). Следующая строка содержит количество запросов q (1 ≤ q ≤ 5·105). Каждая из следующих q строк содержит по два натуральных числа l и r (1 ≤ l, rn) – отрезок, на котором следует найти максимум.

 

Выход. Для каждого запроса выведите максимум на заданном отрезке.

 

Пример входа

Пример выхода

10

5 1 2 8 7 6 10 7 5 6

8

1 10

5 10

1 5

2 6

2 3

7 7

7 8

5 9

10

10

8

8

2

10

10

10

 

 

РЕШЕНИЕ

структуры данных – RMQ

 

Анализ алгоритма

Поскольку модификация элементов отсутствует, то задачу можно решить при помощи RMQ (Range Max Query).

Время предварительной обработки входного массива и построения RMQ массива равно O(nlogn), а время выполнения запроса RMQ(i, j) константно и составляет O(1).

 

Реализация алгоритма

Входную последовательность ai длины n ≤ 105 храним в массиве а. Объявим массив mas для выполнения предобработки данных.

 

#define MAX 100010

#define LOGMAX 17

int mas[MAX][LOGMAX];

int a[MAX];

 

Заполняем массив m так, чтобы mas[i][j] = max(bi, bi+1, …, bi+2^j-1).

 

void Build_RMQ_Array(int *b)

{

  int i, j;

  for (i = 1; i <= n; i++) mas[i][0] = b[i];

  for (j = 1; 1 << j <= n; j++)

    for (i = 1; i + (1 << j) - 1 <= n; i++)

      mas[i][j] = max(mas[i][j - 1], mas[i + (1 << (j - 1))][j - 1]);

}

 

Выполняем запрос RMQ(i, j), возвращающий максимальный элемент в подмассиве a[ij].

 

int RangeMaxQuery(int i, int j)

{

  int temp, k = 0;

  if (i > j) temp = i, i = j, j = temp;

  while ((1 << (k + 1)) <= j - i + 1) k++;

  return max(mas[i][k],mas[j - (1<<k) + 1][k]);

}

 

Основная часть программы. Читаем входные данные.

 

scanf("%d",&n);

for(i = 1; i <= n; i++) scanf("%d",&a[i]);

 

Совершаем препроцессинг. По массиву a строим массив mas.

 

Build_RMQ_Array(a);

 

Последовательно выполняем запросы и выводим их результаты.

 

scanf("%d",&q);

for(i = 0; i < q; i++)

{

  scanf("%d %d",&u,&v);

  printf("%d\n",RangeMaxQuery(u,v));

}